{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "MachineHack-Sentiment-Classification-WinningSolution.ipynb",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-kN3uknh13jL",
        "colab_type": "text"
      },
      "source": [
        "# [Product Sentiment Classification Hackathon](https://www.machinehack.com/hackathons/product_sentiment_classification_weekend_hackathon_19)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kvubc6Xw2BXe",
        "colab_type": "text"
      },
      "source": [
        "### Task 1: Import Libraries and Load the Training Data"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "4j_VGdrcJao7",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 391
        },
        "outputId": "289191ef-71f1-4248-ff8d-cfb01e8a460f"
      },
      "source": [
        "!nvidia-smi"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Mon Sep  7 09:55:12 2020       \n",
            "+-----------------------------------------------------------------------------+\n",
            "| NVIDIA-SMI 450.66       Driver Version: 418.67       CUDA Version: 10.1     |\n",
            "|-------------------------------+----------------------+----------------------+\n",
            "| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |\n",
            "| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |\n",
            "|                               |                      |               MIG M. |\n",
            "|===============================+======================+======================|\n",
            "|   0  Tesla T4            Off  | 00000000:00:04.0 Off |                    0 |\n",
            "| N/A   52C    P8    10W /  70W |      0MiB / 15079MiB |      0%      Default |\n",
            "|                               |                      |                 ERR! |\n",
            "+-------------------------------+----------------------+----------------------+\n",
            "                                                                               \n",
            "+-----------------------------------------------------------------------------+\n",
            "| Processes:                                                                  |\n",
            "|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |\n",
            "|        ID   ID                                                   Usage      |\n",
            "|=============================================================================|\n",
            "|  No running processes found                                                 |\n",
            "+-----------------------------------------------------------------------------+\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "_rlKgYJ-E-b2",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 223
        },
        "outputId": "77944917-b6d9-4376-ff5b-cfd90fe2e62c"
      },
      "source": [
        "!wget https://machinehack-be.s3.amazonaws.com/product_sentiment_classification_weekend_hackathon_19/Participants_Data.zip\n",
        "!unzip -q Participants_Data.zip"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "--2020-09-07 09:55:17--  https://machinehack-be.s3.amazonaws.com/product_sentiment_classification_weekend_hackathon_19/Participants_Data.zip\n",
            "Resolving machinehack-be.s3.amazonaws.com (machinehack-be.s3.amazonaws.com)... 52.219.66.104\n",
            "Connecting to machinehack-be.s3.amazonaws.com (machinehack-be.s3.amazonaws.com)|52.219.66.104|:443... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 400578 (391K) [application/zip]\n",
            "Saving to: ‘Participants_Data.zip’\n",
            "\n",
            "Participants_Data.z 100%[===================>] 391.19K   333KB/s    in 1.2s    \n",
            "\n",
            "2020-09-07 09:55:19 (333 KB/s) - ‘Participants_Data.zip’ saved [400578/400578]\n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hOiL2RdcE-ju",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 36
        },
        "outputId": "5ef2e046-9c29-434d-ebc5-344a10a2e6b4"
      },
      "source": [
        "import tensorflow as tf\n",
        "import tensorflow_hub as hub\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "from sklearn.model_selection import train_test_split\n",
        "\n",
        "df = pd.read_csv('/content/Participants_Data/Train.csv', low_memory=False)\n",
        "df.shape"
      ],
      "execution_count": 1,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(6364, 4)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 1
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QDzmBZdx2RXc",
        "colab_type": "text"
      },
      "source": [
        "### Task 2: Bare Minimum EDA"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yTlnY0fpE-mr",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 206
        },
        "outputId": "c77880da-3e88-4d3b-ac50-ccbfe5bfd219"
      },
      "source": [
        "df.head()"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/html": [
              "<div>\n",
              "<style scoped>\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "</style>\n",
              "<table border=\"1\" class=\"dataframe\">\n",
              "  <thead>\n",
              "    <tr style=\"text-align: right;\">\n",
              "      <th></th>\n",
              "      <th>Text_ID</th>\n",
              "      <th>Product_Description</th>\n",
              "      <th>Product_Type</th>\n",
              "      <th>Sentiment</th>\n",
              "    </tr>\n",
              "  </thead>\n",
              "  <tbody>\n",
              "    <tr>\n",
              "      <th>0</th>\n",
              "      <td>3057</td>\n",
              "      <td>The Web DesignerÛªs Guide to iOS (and Android...</td>\n",
              "      <td>9</td>\n",
              "      <td>2</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>1</th>\n",
              "      <td>6254</td>\n",
              "      <td>RT @mention Line for iPad 2 is longer today th...</td>\n",
              "      <td>9</td>\n",
              "      <td>2</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>2</th>\n",
              "      <td>8212</td>\n",
              "      <td>Crazy that Apple is opening a temporary store ...</td>\n",
              "      <td>9</td>\n",
              "      <td>2</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>3</th>\n",
              "      <td>4422</td>\n",
              "      <td>The lesson from Google One Pass: In this digit...</td>\n",
              "      <td>9</td>\n",
              "      <td>2</td>\n",
              "    </tr>\n",
              "    <tr>\n",
              "      <th>4</th>\n",
              "      <td>5526</td>\n",
              "      <td>RT @mention At the panel: &amp;quot;Your mom has a...</td>\n",
              "      <td>9</td>\n",
              "      <td>2</td>\n",
              "    </tr>\n",
              "  </tbody>\n",
              "</table>\n",
              "</div>"
            ],
            "text/plain": [
              "   Text_ID  ... Sentiment\n",
              "0     3057  ...         2\n",
              "1     6254  ...         2\n",
              "2     8212  ...         2\n",
              "3     4422  ...         2\n",
              "4     5526  ...         2\n",
              "\n",
              "[5 rows x 4 columns]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 2
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "VUvWT2pqE-p4",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 110
        },
        "outputId": "496a15d4-6889-4f8d-a1fe-c639eee48713"
      },
      "source": [
        "df.Sentiment.value_counts()"
      ],
      "execution_count": 3,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "2    3765\n",
              "3    2089\n",
              "1     399\n",
              "0     111\n",
              "Name: Sentiment, dtype: int64"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 3
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "aQoLqQ2YxDgN",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 36
        },
        "outputId": "28074f49-6956-457f-cd4f-51b84c407e9c"
      },
      "source": [
        "df.Product_Type.nunique()"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "10"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ow5qmXzh2gRq",
        "colab_type": "text"
      },
      "source": [
        "### Task 3: Define Feature and Target Matrices"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yP8pXbRCE-tL",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "ONE_HOT_FEATURES = {\n",
        "    \"Product_Type\": 10\n",
        "}\n",
        "\n",
        "TEXT_FEATURES = {\n",
        "    \"Product_Description\": None\n",
        "}"
      ],
      "execution_count": 5,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "l0FyYV7Ontza",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def make_one_hot(df):\n",
        "    one_hot_array = []\n",
        "    for feature_name in ONE_HOT_FEATURES.keys():\n",
        "        temp_array = np.asarray(tf.keras.utils.to_categorical(df[feature_name].values))\n",
        "        ONE_HOT_FEATURES[feature_name] = temp_array.shape[1]\n",
        "        one_hot_array.append(temp_array)\n",
        "\n",
        "    return one_hot_array"
      ],
      "execution_count": 6,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "46eYsalin1Eq",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "for feature in ONE_HOT_FEATURES.keys():\n",
        "    df[feature] = df[feature].astype(\"category\").cat.codes\n",
        "\n",
        "one_hot_x = make_one_hot(df)\n",
        "\n",
        "embedding_x = [np.asarray(df[feature_name].values).reshape(-1) for feature_name in TEXT_FEATURES.keys()]"
      ],
      "execution_count": 7,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "EPOaIRF4E-zJ",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "X = one_hot_x + embedding_x\n",
        "y = np.asarray(df[\"Sentiment\"], dtype=np.uint8).reshape(-1)"
      ],
      "execution_count": 8,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ROaE9i352rO7",
        "colab_type": "text"
      },
      "source": [
        "### Task 4: Define Basic Hyperparamters"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "TavGuzvHzJlk",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "LR = 0.0001\n",
        "BATCH_SIZE = 32\n",
        "EPOCHS = 100"
      ],
      "execution_count": 9,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ddSHOX512yy6",
        "colab_type": "text"
      },
      "source": [
        "### Task 5: Build a Wide and Deep Model (sort of)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "tfV7XHnV28AI",
        "colab_type": "text"
      },
      "source": [
        "Architecture inspired by [Wide & Deep Learning: Better Together with TensorFlow](https://ai.googleblog.com/2016/06/wide-deep-learning-better-together-with.html)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "gTR9TRtVE_As",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def transformed_name(key):\n",
        "    return key + '_xf'\n",
        "\n",
        "def get_model(show_summary=True):\n",
        "    \"\"\"\n",
        "    This function defines a Keras wide and deep model and returns the model as a Keras object.\n",
        "    \"\"\"\n",
        "    \n",
        "    # adding text input features\n",
        "    input_texts = []\n",
        "    for key in TEXT_FEATURES.keys():\n",
        "        input_texts.append(tf.keras.Input(shape=(1,), name=transformed_name(key), dtype=tf.string))\n",
        "    \n",
        "    # adding one-hot encoded features\n",
        "    input_features = []\n",
        "    for key, dim in ONE_HOT_FEATURES.items():\n",
        "        input_features.append(tf.keras.Input(shape=(dim), name=transformed_name(key)))\n",
        "\n",
        "\n",
        "    # embed text features\n",
        "    MODULE_URL = \"https://tfhub.dev/google/universal-sentence-encoder/4\" # almost a gigabyte of weights, yikes!\n",
        "    embed = hub.KerasLayer(MODULE_URL)\n",
        "    reshaped_narrative = tf.reshape(input_texts[0], [-1]) # reshape to match hub layer input, i.e., 1 entry per row\n",
        "    embed_narrative = embed(reshaped_narrative) # outputs 512 dimensional embeddings\n",
        "    deep_ff = tf.keras.layers.Reshape((512, ), input_shape=(1, 512))(embed_narrative)\n",
        "    \n",
        "    deep = tf.keras.layers.Dense(256, activation='relu')(deep_ff) # deep layers for text features\n",
        "    deep = tf.keras.layers.Dropout(0.2)(deep)\n",
        "    deep = tf.keras.layers.Dense(128, activation='relu')(deep)\n",
        "    deep = tf.keras.layers.Dropout(0.1)(deep)\n",
        "    deep = tf.keras.layers.Dense(64, activation='relu')(deep)\n",
        "    #deep = tf.keras.layers.Dense(16, activation='relu')(deep)\n",
        "\n",
        "    wide_ff = input_features[0] # tf.keras.layers.concatenate(input_features) <- use when multiple one-hot features\n",
        "    wide = tf.keras.layers.Dense(64, activation='relu')(wide_ff) # wide layers for one-hot encoded categoricals\n",
        "    #wide = tf.keras.layers.Dense(16, activation='relu')(wide)\n",
        "\n",
        "    both = tf.keras.layers.concatenate([deep, wide])\n",
        "\n",
        "    output = tf.keras.layers.Dense(4, activation='softmax')(both)\n",
        "\n",
        "    inputs = input_features + input_texts\n",
        "\n",
        "    keras_model = tf.keras.models.Model(inputs, output)\n",
        "    keras_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=LR),\n",
        "                        loss='sparse_categorical_crossentropy',  \n",
        "                        metrics=['accuracy'])\n",
        "    if show_summary:\n",
        "        keras_model.summary()\n",
        "\n",
        "    return keras_model"
      ],
      "execution_count": 10,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "_DtvoszBE_Db",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 671
        },
        "outputId": "e75d2ca2-8064-4d55-f222-ca95f08fb52d"
      },
      "source": [
        "model = get_model(show_summary=True)"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Model: \"functional_1\"\n",
            "__________________________________________________________________________________________________\n",
            "Layer (type)                    Output Shape         Param #     Connected to                     \n",
            "==================================================================================================\n",
            "Product_Description_xf (InputLa [(None, 1)]          0                                            \n",
            "__________________________________________________________________________________________________\n",
            "tf_op_layer_Reshape (TensorFlow [(None,)]            0           Product_Description_xf[0][0]     \n",
            "__________________________________________________________________________________________________\n",
            "keras_layer (KerasLayer)        (None, 512)          256797824   tf_op_layer_Reshape[0][0]        \n",
            "__________________________________________________________________________________________________\n",
            "reshape (Reshape)               (None, 512)          0           keras_layer[0][0]                \n",
            "__________________________________________________________________________________________________\n",
            "dense (Dense)                   (None, 256)          131328      reshape[0][0]                    \n",
            "__________________________________________________________________________________________________\n",
            "dropout (Dropout)               (None, 256)          0           dense[0][0]                      \n",
            "__________________________________________________________________________________________________\n",
            "dense_1 (Dense)                 (None, 128)          32896       dropout[0][0]                    \n",
            "__________________________________________________________________________________________________\n",
            "dropout_1 (Dropout)             (None, 128)          0           dense_1[0][0]                    \n",
            "__________________________________________________________________________________________________\n",
            "Product_Type_xf (InputLayer)    [(None, 10)]         0                                            \n",
            "__________________________________________________________________________________________________\n",
            "dense_2 (Dense)                 (None, 64)           8256        dropout_1[0][0]                  \n",
            "__________________________________________________________________________________________________\n",
            "dense_3 (Dense)                 (None, 64)           704         Product_Type_xf[0][0]            \n",
            "__________________________________________________________________________________________________\n",
            "concatenate (Concatenate)       (None, 128)          0           dense_2[0][0]                    \n",
            "                                                                 dense_3[0][0]                    \n",
            "__________________________________________________________________________________________________\n",
            "dense_4 (Dense)                 (None, 4)            516         concatenate[0][0]                \n",
            "==================================================================================================\n",
            "Total params: 256,971,524\n",
            "Trainable params: 173,700\n",
            "Non-trainable params: 256,797,824\n",
            "__________________________________________________________________________________________________\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NiLpx3SGozQx",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 835
        },
        "outputId": "52cb9766-82f7-4135-9375-af24e4453fea"
      },
      "source": [
        "tf.keras.utils.plot_model(model, rankdir='TB', to_file='model.png', dpi=76)"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 12
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "filb-G7O3eBC",
        "colab_type": "text"
      },
      "source": [
        "### Task 6: Train Model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "TsWQfnUhICwE",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 727
        },
        "outputId": "4df871e2-cf3a-4df0-9a40-cc455ad1c48c"
      },
      "source": [
        "es = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=2)\n",
        "#lr_scheduler = tf.keras.callbacks.LearningRateScheduler(scheduler)\n",
        "#checkpoint = tf.keras.callbacks.ModelCheckpoint(filepath='checkpoints', monitor='val_loss', save_best_only=True, save_weights_only=True)\n",
        "\n",
        "history = model.fit(x=X, y=y, batch_size=BATCH_SIZE, validation_split=0.1,\n",
        "                    epochs=EPOCHS, callbacks=[es], verbose=1)"
      ],
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Epoch 1/100\n",
            "179/179 [==============================] - 2s 12ms/step - loss: 1.0502 - accuracy: 0.5774 - val_loss: 0.8984 - val_accuracy: 0.5620\n",
            "Epoch 2/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.8015 - accuracy: 0.6642 - val_loss: 0.8192 - val_accuracy: 0.6766\n",
            "Epoch 3/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.7234 - accuracy: 0.7636 - val_loss: 0.7481 - val_accuracy: 0.7614\n",
            "Epoch 4/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.6519 - accuracy: 0.8100 - val_loss: 0.6787 - val_accuracy: 0.7928\n",
            "Epoch 5/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.5869 - accuracy: 0.8380 - val_loss: 0.6230 - val_accuracy: 0.8022\n",
            "Epoch 6/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.5333 - accuracy: 0.8554 - val_loss: 0.5695 - val_accuracy: 0.8446\n",
            "Epoch 7/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.4863 - accuracy: 0.8729 - val_loss: 0.5352 - val_accuracy: 0.8430\n",
            "Epoch 8/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.4501 - accuracy: 0.8823 - val_loss: 0.5035 - val_accuracy: 0.8540\n",
            "Epoch 9/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.4188 - accuracy: 0.8879 - val_loss: 0.4852 - val_accuracy: 0.8571\n",
            "Epoch 10/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3976 - accuracy: 0.8896 - val_loss: 0.4678 - val_accuracy: 0.8587\n",
            "Epoch 11/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3783 - accuracy: 0.8938 - val_loss: 0.4633 - val_accuracy: 0.8524\n",
            "Epoch 12/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3672 - accuracy: 0.8959 - val_loss: 0.4500 - val_accuracy: 0.8603\n",
            "Epoch 13/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3561 - accuracy: 0.8980 - val_loss: 0.4453 - val_accuracy: 0.8619\n",
            "Epoch 14/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3455 - accuracy: 0.8992 - val_loss: 0.4436 - val_accuracy: 0.8603\n",
            "Epoch 15/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3381 - accuracy: 0.9026 - val_loss: 0.4404 - val_accuracy: 0.8634\n",
            "Epoch 16/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3299 - accuracy: 0.9036 - val_loss: 0.4440 - val_accuracy: 0.8603\n",
            "Epoch 17/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3240 - accuracy: 0.9041 - val_loss: 0.4382 - val_accuracy: 0.8634\n",
            "Epoch 18/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3172 - accuracy: 0.9054 - val_loss: 0.4393 - val_accuracy: 0.8619\n",
            "Epoch 19/100\n",
            "179/179 [==============================] - 2s 10ms/step - loss: 0.3090 - accuracy: 0.9061 - val_loss: 0.4417 - val_accuracy: 0.8634\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TroDEir73rAx",
        "colab_type": "text"
      },
      "source": [
        "### Task 7: Retrain Model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2I8FOL6-D1NR",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#model.load_weights('/content/checkpoints.index')"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "M4FZg3vUFQaT",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "del model\n",
        "model = get_model(show_summary=False)"
      ],
      "execution_count": 18,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "8uuMhAtLExOP",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 335
        },
        "outputId": "38b5c760-a58f-4a8c-89bf-888f5d20b89e"
      },
      "source": [
        "model.fit(x=X, y=y, epochs=8, verbose=1, batch_size=BATCH_SIZE) # retrain on the complete dataset for num_epochs with the lowest val_loss"
      ],
      "execution_count": 19,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Epoch 1/8\n",
            "199/199 [==============================] - 2s 9ms/step - loss: 1.0560 - accuracy: 0.5475\n",
            "Epoch 2/8\n",
            "199/199 [==============================] - 2s 9ms/step - loss: 0.8031 - accuracy: 0.6796\n",
            "Epoch 3/8\n",
            "199/199 [==============================] - 2s 9ms/step - loss: 0.7209 - accuracy: 0.7599\n",
            "Epoch 4/8\n",
            "199/199 [==============================] - 2s 9ms/step - loss: 0.6418 - accuracy: 0.8075\n",
            "Epoch 5/8\n",
            "199/199 [==============================] - 2s 9ms/step - loss: 0.5749 - accuracy: 0.8347\n",
            "Epoch 6/8\n",
            "199/199 [==============================] - 2s 9ms/step - loss: 0.5180 - accuracy: 0.8553\n",
            "Epoch 7/8\n",
            "199/199 [==============================] - 2s 9ms/step - loss: 0.4710 - accuracy: 0.8727\n",
            "Epoch 8/8\n",
            "199/199 [==============================] - 2s 9ms/step - loss: 0.4350 - accuracy: 0.8837\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<tensorflow.python.keras.callbacks.History at 0x7fad0fcc2d68>"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 19
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GNRsrj-j3lCe",
        "colab_type": "text"
      },
      "source": [
        "### Task 8: Test Data Pipeline"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "jmxICLI00KYo",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "test_df = pd.read_csv('/content/Participants_Data/Test.csv', low_memory=False)\n",
        "\n",
        "ONE_HOT_FEATURES = {\n",
        "    \"Product_Type\": 10\n",
        "}\n",
        "TEXT_FEATURES = {\n",
        "    \"Product_Description\": None\n",
        "}\n",
        "\n",
        "for feature in ONE_HOT_FEATURES.keys():\n",
        "    test_df[feature] = test_df[feature].astype(\"category\").cat.codes\n",
        "\n",
        "one_hot_x = make_one_hot(test_df)\n",
        "\n",
        "embedding_x = [np.asarray(test_df[feature_name].values).reshape(-1) for feature_name in TEXT_FEATURES.keys()]\n",
        "X = one_hot_x + embedding_x"
      ],
      "execution_count": 20,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "a6BXwt71Ea8v",
        "colab_type": "text"
      },
      "source": [
        "### Task 9: Model Inference on Test Data"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "hLlebp-HtvRo",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "preds = model.predict(X)"
      ],
      "execution_count": 21,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "QAEyV1-atvYB",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 166
        },
        "outputId": "d8e43a36-2de1-4005-994a-02d541bfab40"
      },
      "source": [
        "preds"
      ],
      "execution_count": 22,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "array([[8.5031018e-03, 4.5976542e-02, 1.9261777e-01, 7.5290257e-01],\n",
              "       [6.2352128e-02, 1.6220716e-01, 6.6587383e-01, 1.0956693e-01],\n",
              "       [6.8597190e-02, 1.5369940e-01, 6.1153215e-01, 1.6617124e-01],\n",
              "       ...,\n",
              "       [2.7805425e-03, 9.2547499e-03, 6.1136659e-02, 9.2682809e-01],\n",
              "       [1.4902602e-03, 8.8806869e-04, 9.3969548e-01, 5.7926159e-02],\n",
              "       [4.7780290e-02, 2.9234186e-01, 1.2856685e-01, 5.3131098e-01]],\n",
              "      dtype=float32)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 22
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ADX44zVGtveH",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "pd.DataFrame(preds, columns=['0', '1', '2', '3']).to_csv('sub.csv', index=False)"
      ],
      "execution_count": 23,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "6yxRxYt9EYt8",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}